# # 自定义中间件实现token鉴权
import re

import rest_framework_simplejwt
from django.contrib.sessions.models import Session
from django.http import JsonResponse
from django.utils import timezone
from django.utils.deprecation import MiddlewareMixin
from django_redis import get_redis_connection
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import AccessToken
from rest_framework_simplejwt.views import TokenRefreshView
from rest_framework.exceptions import AuthenticationFailed
from rest_framework import serializers
from django.contrib.auth import get_user_model

# 获取Django的用户模型
User = get_user_model()


class JwtAuthenticationMiddleware(MiddlewareMixin):
    """
    中间件用于处理通过JWT的身份验证。
    """

    def process_request(self, request):
        # 定义白名单路径，这些路径不需要进行JWT验证
        white_list = ["/user/login", "/login", "/", "/index", "/user/logout", "/verify/",
                      "/verify/image_codes/", "/user/refresh",
                      "/user/test", "/refresh/",
                      "/captcha"]
        # 前端路由
        font_white_list = ["login", "", "index", "sys", "vite.svg","favicon.ico"]
        path = request.path
        pattern = re.compile(r'/([^/]+)')

        match = pattern.match(path)
        if match:
            extracted_content = match.group(1)
            print('path', path, extracted_content)
        else:
            print("No match found, path: ", path)
            extracted_content = ""  # 可以设置一个默认值，或者根据具体情况处理
        print('path', path,extracted_content)
        # 如果请求路径不在白名单和媒体文件路径内，则进行认证
        if (extracted_content not in font_white_list and path not in white_list) and  not path.startswith("/media"):
            print(not path.startswith("/media"))
            try:
                auth_header = request.headers.get('Authorization')
                # print(request.headers.get('Authorization'))
                if not auth_header:
                    return JsonResponse({'error': '未提供有效的 JWT 或 JWT 验证失败！'}, status=401)
                try:
                    prefix, token = auth_header.split(' ')
                    # print(token)
                    if prefix.lower() != 'bearer':
                        raise AuthenticationFailed('Authorization header must start with Bearer')
                except ValueError:
                    raise AuthenticationFailed('Authorization header must contain two space-separated strings')
                validated_token = AccessToken(token)
                # user = self.get_user(validated_token)
                # if user is None:
                #     raise AuthenticationFailed('No user found for this token')
                # (user, validated_token)
                # return
                # print('validated_token', validated_token)
                # print(request.headers.get('Authorization'))
                # 获取token
                # request.headers.get('Authorization')
                # request.META.get('HTTP_AUTHORIZATION')
                # 解码token
                # decoded_token = AccessToken(token)
                # print(decoded_token.payload)
                # if user_auth_tuple is not None:
                #     print(123)
                #     # 如果认证通过，将用户信息存储在请求对象中
                #     request.user, _ = user_auth_tuple
                #     return request  # 返回处理后的请求对象
                #     # 认证失败，没有找到有效的 JWT
            except rest_framework_simplejwt.exceptions.TokenError as e:
                if 'Token is invalid or expired' in str(e):
                    # newToken = self.handle_expired_token(request)
                    # print('newToken', newToken)
                    return JsonResponse({'error': 'Token过期或无效！', 'details': str(e)},
                                        status=419)
                elif 'Token is blacklisted' in str(e):
                    return JsonResponse({'error': 'Token已被列入黑名单！', 'details': str(e)}, status=403)
                else:
                    return JsonResponse({'error': 'Token验证失败！', 'details': str(e)}, status=400)
            except Exception as e:
                return JsonResponse({'error': 'Token处理过程中发生错误！', 'details': str(e)}, status=500)
        # 如果路径在白名单中，继续处理请求而不进行认证
        return None


class SessionCheckMiddleware(MiddlewareMixin):
    """
    中间件用于检查会话是否过期或被销毁。
    """

    def process_request(self, request):
        # 只在用户已登录时进行会话检查
        # 定义白名单路径，这些路径不需要进行JWT验证
        # 后端路由
        # 定义白名单路径，这些路径不需要进行JWT验证
        white_list = ["/user/login", "/login", "/", "/index", "/user/logout", "/verify/",
                      "/verify/image_codes/", "/user/refresh",
                      "/user/test", "/refresh/",
                      "/captcha"]
        # 前端路由
        font_white_list = ["login", "", "index", "sys", "vite.svg"]
        path = request.path
        pattern = re.compile(r'^\/([^\/]+)')
        match = pattern.match(path)

        if match:
            extracted_content = match.group(1)
            print('path', path, extracted_content)
        else:
            print("No match found, path: ", path)
            extracted_content = ""  # 可以设置一个默认值，或者根据具体情况处理
        print('path', path)
        # 如果请求路径不在白名单和媒体文件路径内，则进行认证
        if (extracted_content not in font_white_list and path not in white_list) and not path.startswith("/media"):

            print('123request.session', request.session)
            # 4.把uuid和图片文本存入redis
            # redis_client = get_redis_connection('session')  # 获取redis客户端
            # 5.写入redis(是字符串)
            # redis_client.setex('session:' + uuid, 60 * 5, text)
            redis_client_session = get_redis_connection('session')  # 获取redis客户端
            # sessionid = redis_client_session.get('session:' + request.COOKIES.get('uuid'))
            # user_session = Session.objects.get(session_key=request.session.session_key)
            # sessionId = request.session.get('sessionid')
            sessionId = request.session.session_key
            session_key = redis_client_session.get('session:' + request.COOKIES.get('userId'))
            print('判断', sessionId, session_key.decode('utf-8'))
            if sessionId != session_key.decode('utf-8'):
                request.session.flush()
                return JsonResponse({'error': 'session过期！', }, status=401)
                # print('111111111111111',sessionId)
            if not sessionId:
                request.session.flush()
                return JsonResponse({'error': 'session销毁！', }, status=401)
                # print('123request.session', user_session)
            # except Session.DoesNotExist:
            #     request.session.flush()

            # if user_session.expire_date < timezone.now():
            #     request.session.flush()
            #     return JsonResponse({'error': 'session过期！', }, status=401)

        return None
